package top.lshaci.framework.file.oss.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyun.oss.model.GetObjectRequest;
import top.lshaci.framework.file.service.FileOperateService;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.function.Supplier;

/**
 * OssFileOperateService
 *
 * @author lshaci
 * @since 1.0.9
 */
public interface OssFileOperateService extends FileOperateService {

    /**
     * 阿里云中 bucket 的名称
     *
     * @return bucket <b>framework.file.oss.bucket</b>
     */
    String bucket();

    /**
     * 上传对象到 阿里云 oss 中
     *
     * @param inputStream 对象的输入流
     * @param extName     对象扩展名(不含<b>.</b>)
     * @return 阿里云 oss 中的地址
     * @throws IOException 如果产生 I/O 异常
     */
    @Override
    default String upload(InputStream inputStream, String extName) throws IOException {
        return single(inputStream, bucket(), () -> StrUtil.format("{}{}{}", IdUtil.objectId(), StrUtil.DOT, extName));
    }

    /**
     * 上传对象到 阿里云 oss 中
     *
     * @param inputStream  对象的输入流
     * @param bucket       阿里云 oss 中的 bucket
     * @param pathSupplier 对象地址生成方式
     * @return 阿里云 oss 中的地址
     * @throws IOException 如果产生 I/O 异常
     */
    String single(InputStream inputStream, String bucket, Supplier<String> pathSupplier) throws IOException;

    /**
     * 根据对象地址, 删除阿里云 oss 中的对象
     *
     * @param path 对象地址
     */
    @Override
    default void delete(String path) {
        delete(bucket(), path);
    }

    /**
     * 根据对象地址集合删除 oss 中多个对象
     *
     * @param pathList 对象地址集合
     */
    @Override
    default void delete(List<String> pathList) {
        delete(bucket(), pathList);
    }

    /**
     * 根据对象地址, 删除阿里云 oss 指定 bucket 中的对象
     *
     * @param bucket 阿里云 oss 中的 bucket
     * @param path   对象地址
     */
    void delete(String bucket, String path);

    /**
     * 根据对象地址集合, 删除阿里云 oss 指定 bucket 中多个对象
     *
     * @param bucket   阿里云 oss 中的 bucket
     * @param pathList 对象地址集合
     * @return 删除结果
     */
    default DeleteObjectsResult delete(String bucket, List<String> pathList) {
        DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucket);
        deleteObjectsRequest.setKeys(pathList);
        return delete(deleteObjectsRequest);
    }

    /**
     * 根据删除对象请求, 删除阿里云 oss 中的对象
     *
     * @param deleteObjectsRequest 删除对象请求
     * @return 删除结果
     */
    DeleteObjectsResult delete(DeleteObjectsRequest deleteObjectsRequest);

    /**
     * 根据对象地址, 在阿里云 oss 或获取对象 指定 bucket 中的对象
     *
     * @param path         阿里云 oss 中的对象地址
     * @param outputStream 输出流
     */
    @Override
    default void write(String path, OutputStream outputStream) {
        write(bucket(), path, outputStream);
    }

    /**
     * 根据对象地址, 在阿里云 oss 指定 bucket 中或获取对象
     *
     * @param bucket       阿里云 oss 中的 bucket
     * @param path         阿里云 oss 中的对象地址
     * @param outputStream 输出流
     */
    default void write(String bucket, String path, OutputStream outputStream) {
        final GetObjectRequest request = new GetObjectRequest(bucket, path);
        write(request, outputStream);
    }

    /**
     * 根据获取对象请求, 在阿里云 oss 中获取对象
     *
     * @param request 获取对象请求
     * @param outputStream 输出流
     */
    void write(GetObjectRequest request, OutputStream outputStream);

}
